package aor2.cpu.blockregisters;

import aor2.components.Element;
import aor2.components.ElementIO;
import aor2.components.Register;
import aor2.components.Restorable;
import aor2.cpu.InternBus;
import aor2.cpu.blockcontrol.ControlSignalSet;

public enum GPRegisters implements Element, ElementIO, Restorable {
	R0(0, InternBus.M1, InternBus.M2), R1(0, InternBus.M1, InternBus.M2), R2(0,
			InternBus.M1, InternBus.M2), R3(0, InternBus.M1, InternBus.M2), R4(
			0, InternBus.M1, InternBus.M2), R5(0, InternBus.M1, InternBus.M2), R6(
			0x300, InternBus.M1, InternBus.M2), R7(0, InternBus.M1, InternBus.M2);

	static {
		ControlSignalSet css = ControlSignalSet.getInstance();
		css.get("PCin").addDestinationElementIO(R7);
		css.get("SPin").addDestinationElementIO(R6);
		css.get("PCout").addSourceElementIO(R7);
		css.get("SPout").addSourceElementIO(R6);
	}

	private Register reg;

	@Override
	public long getState() {
		return reg.getState();
	}

	@Override
	public void setState(long state) {
		reg.setState(state);
	}

	public void out() {
		reg.out();
	}

	public void in() {
		reg.in();
	}

	private GPRegisters(long state, Element input, Element output) {
		this.reg = new Register(state, input, output);
	}

	public static String info() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("R0[" + R0.getState() + "]\n");
		buffer.append("R1[" + R1.getState() + "]\n");
		buffer.append("R2[" + R2.getState() + "]\n");
		buffer.append("R3[" + R3.getState() + "]\n");
		buffer.append("R4[" + R4.getState() + "]\n");
		buffer.append("R5[" + R5.getState() + "]\n");
		buffer.append("R6<->SP[" + R6.getState() + "]\n");
		buffer.append("R7<->PC[" + R7.getState() + "]");
		return buffer.toString();
	}

	@Override
	public void restore(String restorePoint) {
		String trim = restorePoint.replace(beginTag(), "");
		trim = trim.replace(endTag(), "");
		trim = trim.trim();
		String[] states = trim.split(" ");

		R0.reg.setState(Long.parseLong(states[0]));
		R1.reg.setState(Long.parseLong(states[1]));
		R2.reg.setState(Long.parseLong(states[2]));
		R3.reg.setState(Long.parseLong(states[3]));
		R4.reg.setState(Long.parseLong(states[4]));
		R5.reg.setState(Long.parseLong(states[5]));
		R6.reg.setState(Long.parseLong(states[6]));
		R7.reg.setState(Long.parseLong(states[7]));

	}

	@Override
	public String createRestorePoint() {
		return beginTag() + "\n\t" + R0.reg.getState() + " "
				+ R1.reg.getState() + " " + R2.reg.getState() + " "
				+ R3.reg.getState() + " " + R4.reg.getState() + " "
				+ R5.reg.getState() + " " + R6.reg.getState() + " "
				+ R7.reg.getState() + " " + "\n" + endTag();
	}

	@Override
	public String beginTag() {
		return "<GPR>";
	}

	@Override
	public String endTag() {
		return "</GPR>";
	}

}
